package com.chenjt.netty.one_helloWorld.executeFlow;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

import java.net.URI;

/**
 * 注释：SimpleChannelInboundHandler : Inbound:对进来请求的处理  OutBound：响应的处理
 *
 * @author chenjt
 * @date 2024/8/8 9:42
 */
public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {

    /**
     * 读取客户端的请求，并响应客户端
     * 注意：netty5.0的这个方法叫做messageReceived
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {

        if(msg instanceof HttpRequest){

            HttpRequest httpRequest = (HttpRequest)msg;

            System.out.println("请求方法名：" + httpRequest.method().name());

            URI uri = new URI(httpRequest.uri());
            if("/favicon.ico".equals(uri.getPath())){
                // 浏览器访问时会有这个请求
                System.out.println("请求favicon.ico");
                return;
            }

            ByteBuf content = Unpooled.copiedBuffer("Hello World", CharsetUtil.UTF_8);
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
                    HttpResponseStatus.OK, content);

            // 构建响应头
            // 这里用test/plain会导致浏览器访问时会以下载的方式响应
            // response.headers().set(HttpHeaderNames.CONTENT_TYPE,"test/plain");
            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"application/json");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());

            // 调用writer只会把内容放到缓冲区里面，不会立即返回给客户端
            ctx.writeAndFlush(response);
            ctx.channel().close();
        }

    }


    /**
     * 以下所有方法的执行顺序
     * 没有ctx.channel().close();之前
     * 浏览器第一次访问结果如下（当等待时间足够长之后会就会出现inactive和unregistered,由http1.1的keep-alive定的时间所决定）：
     *      请求方法名：GET
     *      channel inactive
     *      channel unregistered
     *      请求方法名：GET
     *      请求favicon.ico
     *  当浏览器退出时结果如下：
     *          channel inactive
     *          channel unregistered
     *
     *  curl结果如下：
     *      handler added
     *      channel registered
     *      channel active
     *      请求方法名：GET
     *      channel inactive
     *      channel unregistered
     */

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channel active");
        super.channelActive(ctx);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channel registered");
        super.channelRegistered(ctx);
    }

    /**
     * 通道被添加
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handler added");
        super.handlerAdded(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channel inactive");
        super.channelInactive(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channel unregistered");
        super.channelUnregistered(ctx);
    }
}
